<!--
 * @Descripttion : 
 * @Autor        : Lilong
 * @Date         : 2022-10-08 16:07:07
 * @LastEditTime : 2022-10-09 09:44:58
 * @FilePath     : \src\App.vue
-->
<script setup lang="ts">
import {reactive, ref, toRef, toRefs} from 'vue'

type User = {
  id: number,
  name: string
}
let num:number = 1
let obj:User = {id: 1, name: 'lilong' }

/**
 * 声明基础类型
 * reactive无法声明基础类型，因为reacitve中类型接收的必须是object
 */ 

// const refNum = reactive(num)    

/**
 * 声明引用类型
 */
const refObj = reactive<User>(obj)
console.log('refObj', refObj.name)    

console.log('===============')

const refCount = ref<number>(0)

console.log('======当ref作为响应式对象的属性被访问或更改时，它会自动展开内部值,无需.value =========')

const reactiveState = reactive({
  refCount
})
console.log('reactiveState', reactiveState)
console.log('自动展开内部值', reactiveState.refCount)  //0， 无需.value

console.log('===============')

reactiveState.refCount = 1
console.log('ref包裹的', refCount.value)  //1
console.log('自动展开内部值', reactiveState.refCount)  //1，无需.value

console.log('===============')

refCount.value = 2
console.log('ref包裹的', refCount.value)  //2
console.log('自动展开内部值', reactiveState.refCount)  //2，无需.value


console.log('======当ref作为响应式Array或原生集合类型(如Map、等)被访问或更改时，不会自动展开内部值，需.value =========')

const reactiveArray = reactive<Array<any>>([
  ref('Vue3')
])
const reactiveMap = reactive<Map<string, any>>(new Map([['count', ref(0)]]))
console.log('reactiveArray[0].value', reactiveArray[0].value)   //Vue3
console.log('reactiveMap.get("count").value', reactiveMap.get("count").value)   //0

console.log('======改变内层属性，会导致该处dom重新渲染=========')
const reactiveObj = reactive({
  id:1,
  name: 'lilong',
  childrens: {
    id: 11,
    name: 'tiantian'
  }
})
const reactiveObj1 = reactive({
  sex:'男',
  name: 'lilong',
  age: 32,
  childrens: {
    sex: '女',
    age: 1
  }
})
//解构出来的属性，响应性丢失(数组一样)
const {id, childrens: {name}} = reactiveObj
const { sex } = toRefs(reactiveObj1)    //需要用toRefs包裹，转换成一组ref，响应性才不会丢失

const change = () => {
  reactiveObj.childrens.name = 'tiantian1'
  sex.value = '女'
}

</script>

<template>
  <h3>reactive：</h3>
  <h5>
    作用：常用于深层次响应式对象，常用于声明引用类型值（Object 、Array）
  </h5>
  <h5>
    注意：<br>
    1、reactive声明的引用类型在模板和js中都无需.value <br>
    2、reactive创建的引用类型数据，和以前相关，与js中的引用数据类型表现一致，即reactive包裹前后相互影响，相当于引用 <br>
    3、当ref作为响应式对象的属性被访问或更改时，它会自动展开内部值,无需.value <br>
    4、当ref作为响应式Array或原生集合类型(如Map、等)被访问或更改时，不会自动展开内部值，需.value <br>
    5、从对象或数组正常解构出来的属性等，会丢失响应性，应用toRefs包裹解构出来才不会丢失响应性 <br>
    6、reactive响应式转换是“深度转换”——它会影响嵌套对象传递的所有属性，改变内层属性，会导致该处dom重新渲染 <br>
  </h5>
  <h5>声明引用类型</h5>
  <ul>
    <li>refObj.name: {{refObj.name}}</li>
    <li>reactiveState.refCount:{{reactiveState.refCount}}</li>
    <li>reactiveObj：{{ reactiveObj }}</li>
    <li>reactiveObj解构出来的父级id：{{ id }}</li>
    <li>reactiveObj解构出来的子级name：{{ name }}</li>
    <li>reactiveObj1解构出来的父级sex：{{ sex }}</li>
  </ul>
  <button @click="change">改变reactiveObj</button>
</template>

<style scoped>
ul,li{
  list-style: none;
}
</style>
